#include<Algorithm/intersection_of_two_surfaces.h>
#include<tool/libcell_tools_octree.h>
#include<tool/libcell_octree_iterator.h>
#include<Mesh/libcell_iterator.h>
#define DEFAULT_THRESHOLD  1e-6
#define quote lib_cell_quote

void mesh2_crossover_point_free(Mesh2_Crossover_Point*mcp)
{
    for(auto it=mcp->v2p->begin(mcp->v2p);it.it!=NULL;it++)
    {
        free_node((Node*)(it.second));
    }
    int_rb_tree_free(mcp->v2p);
    for(auto it=mcp->f2p->begin(mcp->f2p);it.it!=NULL;it++)
    {
        free_node((Node*)(it.second));
    }
    int_rb_tree_free(mcp->f2p);
    for(auto it=mcp->c2p->begin(mcp->c2p);it.it!=NULL;it++)
    {
        free_node((Node*)(it.second));
    }
    int_rb_tree_free(mcp->c2p);
   
    mcp->v2p=NULL;mcp->f2p=NULL;mcp->c2p=NULL;
} 
// static inline int is_same_point(double *p1,double *p2)
// {
//     if(fabs(p1[0]-p2[0])<DEFAULT_THRESHOLD&&fabs(p1[1]-p2[1])<DEFAULT_THRESHOLD&&fabs(p1[2]-p2[2])<DEFAULT_THRESHOLD)
//     {
//         return 1;
//     }
//     return 0; 
// }
static inline int is_same_point(double *p1,double *p2)
{
    if(fabs(p1[0]-p2[0])<1e-7&&fabs(p1[1]-p2[1])<1e-7&&fabs(p1[2]-p2[2])<1e-7)
    {
        return 1;
    }
    return 0; 
}
static inline int is_same_point2(double *p1,double *p2,double threshold)
{
    if(fabs(p1[0]-p2[0])<=threshold&&fabs(p1[1]-p2[1])<=threshold&&fabs(p1[2]-p2[2])<=threshold)
    {
        return 1;
    }
    return 0; 
}
// static int is_four_points_coplanar(double* p1,double* p2,double* p3,double* p4)
// {
// 
// }

static Node* get_intersection_from_two_cells(template_c* c1,template_c* c2)
{
    int len1=c1->vertices_size,len2=c2->vertices_size;
    double**poly1=(double**)malloc(sizeof(double*)*len1);
    double**poly2=(double**)malloc(sizeof(double*)*len2);

    Node* hfs=Mesh_adjust_halffaces(c1);
    int i=0;
    for(Node*nit=hfs;nit!=NULL;nit=(Node*)(nit->Next))
    {
        poly1[i]=((template_hf*)(nit->value))->vertices[0]->point;
        i++;
    }
    free_node(hfs);
    hfs=Mesh_adjust_halffaces(c2);
    i=0;
    for(Node*nit=hfs;nit!=NULL;nit=(Node*)(nit->Next))
    {
        poly2[i]=((template_hf*)(nit->value))->vertices[0]->point;
        i++;
    }
    free_node(hfs);
    // printf("intersection c1 ：%d c2:%d\n",c1->id,c2->id);

// 不管 poly1 poly2 是不是在一个平面，返回的是相交区域，可以是null,点，线，面
// 保证poly1和poly2是凸的
    Node* re=NULL;
    int poly_len=0;
    double**poly=(double**)malloc(sizeof(double*)*(len1+len2));
    for(i=0;i<len1+len2;i++)
    {
        poly[i]=(double*)malloc(sizeof(double)*3);
        memset(poly[i],0,sizeof(double)*3);  
    }
    get_intersections_from_two_polygons(poly1,len1,
        poly2 ,len2,poly,&poly_len);
    // if(poly_len>2)
    // {
    for(i=0;i<len1+len2;i++)
    {   
        if(i<poly_len)
        {
            re=node_pushback(re,poly[i] );
        }
        else
        {
            free(poly[i]);
        }
    }
    re=node_reverse(re); 
    // }

    

    
    free(poly1);free(poly2);  
    
    return re;
}


static Node* get_intersections_of_one_cells(template_c*c, Mesh2_Crossover_Point* mcp)
{   
    Node* re=NULL;
    for(int i=0;i<c->vertices_size;i++)
    {
        Node*node=(Node*)(mcp->v2p->find(mcp->v2p,c->vertices[i]->id));
        re=node_plus(re,node_copy(node));
    }

    //for(Node* hfit=c->halffaces;hfit!=NULL;hfit=(Node*)(hfit->Next))
    for(auto chfit=Mesh_chf_begin(NULL,*c);chfit!=Mesh_chf_end(NULL,*c);chfit++)
    {
        template_f* f=quote(chfit)->face;
        Node* node=(Node*)(mcp->f2p->find(mcp->f2p,f->id));
        re=node_plus(re,node_copy(node));
    }
    Node* node=(Node*)(mcp->c2p->find(mcp->c2p,c->id));
    re=node_plus(re,node_copy(node));
    return re;
}

// // mcp 储存了c元素上附着点的信息

static template_v* is_exist_same_point_in_cells(template_c* c1,Mesh2_Crossover_Point* mcp1,
    template_c* c2,Mesh2_Crossover_Point* mcp2,double* p)
{
    Node*node1=get_intersections_of_one_cells(c1, mcp1);
    Node*node2=get_intersections_of_one_cells(c2, mcp2);
    template_v*re=NULL;
    Node*node_inter= node_intersection(node1,node2);
    for(Node* nit=node_inter;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_v*v=(template_v*)(nit->value);
        //这里修改，程序不会崩溃
        //

        if(is_same_point(v->point,p))
        //if(distance_of_two_points(v->point,p,3)<1e-4)
        {
            re=v;
            break;
        }
    }

    free_node(node1);free_node(node2);free_node(node_inter);
    return re;
}


static inline void my_insert_value2tree(Int_RB_Tree* tree,int id,void* v)
{
    Node* value=(Node*)(tree->find(tree,id));
    if(value==NULL)
    {
        value=node_overlying(value,v);
        tree->insert(tree,id,value);
        return ;
    }
    Node* v_n=node_reverse(value);
    v_n=node_pushback(v_n,v);

}


static inline void my_erase_value_from_tree(Int_RB_Tree* tree,int id,void*v)
{
    Node* value=(Node*)(tree->find(tree,id));
    if(value==NULL)
    {
        return ;
    }
    value=node_delete_value(value,v);
    tree->insert(tree,id,value);
}

static double distance_of_from_line_segment2point(double* p1,double* p2,double*p)
{
    double dir1[3]={p[0]-p1[0],p[1]-p1[1],p[2]-p1[2] };
    double dir2[3]={p[0]-p2[0],p[1]-p2[1],p[2]-p2[2] };
    double dir3[3]={p1[0]-p2[0],p1[1]-p2[1],p1[2]-p2[2] };
    if(inner_product(dir1,dir3,3)*inner_product(dir2,dir3,3)<0)
    {
        if(normalize(dir3,3))
        {
            double temp=inner_product(dir3,dir2,3);
            double temp1=dir2[0]*dir2[0]+dir2[1]*dir2[1]+dir2[2]*dir2[2]- temp*temp;
            return SAFE_SQRT(temp1);
        }
    }
    double temp2=distance_of_two_points(p1,p,3);
    double temp3=distance_of_two_points(p2,p,3);
    
    return (temp2<temp3?temp2:temp3);
}
// // mcp 储存c元素上附着点的信息
// // scp是上面的逆信息
// //
static void vertex_attachment_to_celln(template_c*c,
    template_v* nv,Mesh2_Crossover_Point* mcp,
    SCrossover_Point * scp)
{
    for(int i=0;i<c->vertices_size;i++)
    {
        //这里修改程序都不会崩溃
        if(is_same_point(nv->point,c->vertices[i]->point))
        //if(distance_of_two_points(nv->point,c->vertices[i]->point,3)<1e-4)
        {
            my_insert_value2tree(mcp->v2p,c->vertices[i]->id,nv);
            scp->v=c->vertices[i];
            return ;
        }  
    } 

    template_f*f=NULL;double temp_dis=1.8e-7;
    //for(Node* hfit=c->halffaces;hfit!=NULL;hfit=(Node*)(hfit->Next))
    for(auto chfit=Mesh_chf_begin(NULL,*c);chfit!=Mesh_chf_end(NULL,*c);chfit++)
    {
        template_f*f1=quote(chfit)->face;
        double temp_dis1=distance_of_from_line_segment2point(f1->vertices[0]->point,f1->vertices[1]->point,nv->point);
        if(temp_dis1<temp_dis)
        {
            temp_dis=temp_dis1;
            f=f1;
        }
        // double * l=get_line_equation_from_two_points(f->vertices[0]->point,f->vertices[1]->point);
        // if(l==NULL)
        // {
        //     continue;
        // } 
        // double distance= distance_from_point_to_line(nv->point,l);
        // free(l);
        // if(distance<1e-4)
        // {
        //     my_insert_value2tree(mcp->f2p,f->id,nv);
        //     scp->f=f;
        //     return;
        // } 
    }
    if(f!=NULL)
    {
        my_insert_value2tree(mcp->f2p,f->id,nv);
        scp->f=f;
        return ;
    }

    my_insert_value2tree(mcp->c2p,c->id,nv); 
    scp->c=c; 
    return ;
}

static int is_two_cell_maybe_inter(template_c* c1,template_c* c2)
{
    double min1[3]={c1->vertices[0]->point[0],c1->vertices[0]->point[1],c1->vertices[0]->point[2] },
        max1[3]={c1->vertices[0]->point[0],c1->vertices[0]->point[1],c1->vertices[0]->point[2]};

    for(int i=1;i<c1->vertices_size;i++)
    {
        for(int j=0;j<3;j++)
        {
            c1->vertices[i]->point[j]<min1[j]?(min1[j]=c1->vertices[i]->point[j]):(c1->vertices[i]->point[j]>max1[j]?(max1[j]=c1->vertices[i]->point[j]):i=i);

        }
    }
    double min2[3]={c2->vertices[0]->point[0],c2->vertices[0]->point[1],c2->vertices[0]->point[2] },
        max2[3]={c2->vertices[0]->point[0],c2->vertices[0]->point[1],c2->vertices[0]->point[2]};
    
    for(int i=1;i<c2->vertices_size;i++)
    {
        for(int j=0;j<3;j++)
        {
            c2->vertices[i]->point[j]<min2[j]?(min2[j]=c2->vertices[i]->point[j]):(c2->vertices[i]->point[j]>max2[j]?(max2[j]=c2->vertices[i]->point[j]):i=i);

        }
    }

    if(min2[0]>max1[0]+DEFAULT_THRESHOLD||min2[1]>max1[1]+DEFAULT_THRESHOLD||min2[2]>max1[2]+DEFAULT_THRESHOLD)
    {
        return 0;
    }
    if(max2[0]<min1[0]+DEFAULT_THRESHOLD||max2[1]<min1[1]+DEFAULT_THRESHOLD||max2[2]<min1[2]+DEFAULT_THRESHOLD) 
    {
        return 0;
    }
    return 1;
}

static inline void show_attach_info(SCrossover_Point*scp)
{
    if(scp->v!=NULL)
    {
        printf("attach v %d\n",scp->v->id);
    }
    else if(scp->f!=NULL)
    {
        printf("attach f:%d %d %lf %lf %lf\n",scp->f->vertices[0]->id,scp->f->vertices[1]->id 
            ,scp->f->vertices[1]->point[0],scp->f->vertices[1]->point[1],scp->f->vertices[1]->point[2]);
    }
    else if(scp->c!=NULL)
    {
        printf("attach c:%d\n",scp->c->id);
    }
}
//m是新建点的信息网格
//mcp1储存c1上元素的附着点信息
//mcp2储存c2上元素的附着点信息

static template_v** get_intersection_vertices_from_two_cells(template_m*m,template_c* c1,template_c* c2,
    Mesh2_Crossover_Point * mcp1,Mesh2_Crossover_Point * mcp2,int* len)
{
    if(is_two_cell_maybe_inter(c1,c2)==0)
    {
        return NULL;
    }
    Node*poly= get_intersection_from_two_cells(c1,c2);
    *len=node_size(poly); 
    if(poly==NULL)
    {return NULL;}
    
    // if(c1->id==7258||c1->id==7255)
    // {
    //     printf("%d len:%d\n",c1->id,len);
    // }
    double *p=NULL;
    template_v** re=(template_v**)malloc(sizeof(template_v*)*(*len) );
    memset(re,0,sizeof(template_v*)*(*len) );
    int i=0;
    for(Node* nit=poly;nit!=NULL;nit=(Node*)(nit->Next))
    {
        p=(double*)(nit->value);
        re[i]=is_exist_same_point_in_cells(c1,mcp1,c2,mcp2,p);
        if(re[i]==NULL)
        { 
            // if(c1->id==7258||c1->id==7255)
            // {
            //     printf("is null\n");
            // }

            re[i]=m->create_vertexv(m,p,3);


            Crossover_Point *cp=(Crossover_Point*)malloc(sizeof(Crossover_Point));
            crossover_point_init(cp);  
            re[i]->prop=cp;
            vertex_attachment_to_celln(c1,re[i],mcp1,&(cp->scp[0]));
            vertex_attachment_to_celln(c2,re[i],mcp2,&(cp->scp[1]));
            if(re[i]->id==6721||re[i]->id==6722||re[i]->id==6718||re[i]->id==6717
                )
            {
                printf("re id:%d c1:%d c2:%d %lf %lf %lf\n",re[i]->id,c1->id,c2->id,
                    re[i]->point[0],re[i]->point[1],re[i]->point[2]);
                double * p1=(double*)(node_at(poly,0)->value);
                double * p2=(double*)(node_at(poly,1)->value);
                printf("len:%d %lf %lf %lf %lf %lf %lf dis:%lf\n",*len,p1[0],p1[1],p1[2],p2[0],p2[1],p2[2],
                    distance_of_two_points(p1,p2,3));
                show_attach_info(&(cp->scp[0]));
                show_attach_info(&(cp->scp[1]));

            }
        }
        i++;
        // if(c1->id==7258||c1->id==7255)
        // {
        //     printf("null %d\n",re[i]->id);
        // }
    } 
  
    free_node_value(poly);
    free_node(poly);

    return re;
}
// 
/// 修改如果vs里两个点相等的情况
// 
static template_c* my_create_cellfv(Mesh*m,template_v**vs,int len )
{
    for(int i=0;i<len;i++)
    {
        for(int j=i+1;j<len;j++)
        {
            if(vs[j]==vs[i]){vs[j]=NULL;}
        }
    }
    int len1=0;
    for(int i=0;i<len;i++)
    {
        if(vs[i]!=NULL){
            vs[len1]=vs[i];
            len1++;
        }
    }
    template_hf** temp_hf=(template_hf**)malloc(sizeof(template_hf*)*len1);
    for(int i=0;i<len1;i++)
    {
        template_v* vs1[2]={vs[i],vs[((i+1)%len1)]};
        template_f* f=m->create_facev(m,vs1,2);
        temp_hf[i]=m->create_halfface(m,f,vs1,2);
    }
    template_c*re= m->create_cellf(m,temp_hf,len1);

    free(temp_hf);

    return re;

}

void  get_intersection_lines_of_two_nodes(Mesh* m,Node* n1,Node* n2,
    Mesh2_Crossover_Point* mcp1,Mesh2_Crossover_Point* mcp2)
{ 
    if(n1==NULL||n2==NULL)
    {return ;}
   
    for(Node* it1=n1;it1!=NULL;it1=(Node*)(it1->Next))
    {
        template_c* c1=(template_c*)(it1->value);
        for(Node* it2=n2;it2!=NULL;it2=(Node*)(it2->Next))
        {
            template_c*c2=(template_c*)(it2->value);
            int len=0;
            template_v** vs=get_intersection_vertices_from_two_cells(m,
                c1,c2,mcp1,mcp2,&len);

            if(vs==NULL)
            {continue;}
            if(len==2)
            {
                if(vs[0]!=NULL&&vs[1]!=NULL&&vs[0]!=vs[1]){m->create_facev(m,vs,2);}
            }
            else if(len>2)
            {
                my_create_cellfv(m,vs, len );
            }
            // if(vs[0]!=NULL&&vs[1]!=NULL)
            // {
            //     
            // } 
            free(vs);
        }
    } 
}
Mesh* get_intersection_lines_of_two_nodesn(Node* n1,Node* n2,
    Mesh2_Crossover_Point*mcp1,Mesh2_Crossover_Point*mcp2)
{
    Node* in=get_maybe_intersecting_areas_from_nodes(n1,n2);
    Mesh* re=(Mesh*)malloc(sizeof(Mesh));
    Mesh_init(re);
    re->simplex=0;
    re->manifold_require=0;
    re->dimension=2;
    for(Node* nit=in;nit!=NULL;nit=(Node*)(nit->Next))
    {

        Maybe_Intersecting_Areas* mia=(Maybe_Intersecting_Areas*)(nit->value);

        get_intersection_lines_of_two_nodes(re,mia->node1,mia->node2,mcp1,mcp2);
        maybe_intersecting_areas_free(mia);  

    }
    free_node(in);
    return re;
}
Mesh*  get_intersection_lines_of_two_meshs(Mesh* m1,Mesh* m2,
    Mesh2_Crossover_Point* mcp1,Mesh2_Crossover_Point*mcp2)
{ 
    Node* n1=NULL,*n2=NULL; 
    for(auto it=m1->c_begin(m1);it!=m1->c_end(m1);it++)
    {
        n1=node_overlying(n1,quote(it));
    } 
    for(auto it=m2->c_begin(m2);it!=m2->c_end(m2);it++)
    {
        n2=node_overlying(n2,quote(it));
    }
    Mesh* re=get_intersection_lines_of_two_nodesn(n1,n2,mcp1,mcp2);
    free_node(n1);free_node(n2);
   

    return re;
 }

static inline void my_unregister_crossover_point(SCrossover_Point*sp, Mesh2_Crossover_Point*mcp,template_v*v)
{
    if(sp->v!=NULL)
    {
        my_erase_value_from_tree(mcp->v2p,sp->v->id,v);
    }
    else if(sp->f!=NULL)
    {
        my_erase_value_from_tree(mcp->f2p,sp->f->id,v);
    }
    else 
    {
        my_erase_value_from_tree(mcp->c2p,sp->c->id,v);
    }

}
//

static void my_jiaohuan_vertices_value(template_v**vs,template_v*v1,template_v*v2,int len)
{
    for(int i=0;i<len;i++)
    {
        if(vs[i]==v1)
        {
            vs[i]=v2;
            return;
        }
    }

}

static void merge_two_vertices(Mesh* m,template_v* v,template_v* v1,
    Mesh2_Crossover_Point* mcp1,Mesh2_Crossover_Point*mcp2)
{ 
    Crossover_Point* cp=(Crossover_Point*)(v1->prop),*cp1=(Crossover_Point*)(v->prop);
    Mesh2_Crossover_Point* mcps[2]={mcp1,mcp2};
    printf("erase v id:%d save id:%d\n",v1->id,v->id);
    for(int i=0;i<2;i++)
    {
        my_unregister_crossover_point(&(cp->scp[i]),mcps[i],v1);
    }
    template_v* vs[2]={v,NULL};

    Node* f_vs=NULL;
    Node* cell_vs=NULL,*temp_node=NULL;
    // for(Node*nit=v1->cells;nit!=NULL;nit=(Node*)(nit->Next))
    for(auto vcit=m->vc_begin(m,*v1);vcit!=m->vc_end(m,*v1);vcit++)
    {
        template_c*c=quote(vcit);
        // template_c*c=(template_c*)(nit->value);
        temp_node=node_overlying(temp_node,c);
        template_v**vs=(template_v**)malloc(sizeof(template_v*)*c->vertices_size);
        Node* hfs=Mesh_adjust_halffaces(c);
        cell_vs=node_overlying(cell_vs,vs);
        int i=0;
        for(Node* nit1=hfs;nit1!=NULL;nit1=(Node*)(nit1->Next))
        {
            template_hf* hf=(template_hf*)(nit1->value);
            vs[i]=hf->vertices[0];
            i++;
        }
        int* int_value=(int*)malloc(sizeof(int));
        *int_value=i;
        cell_vs->traits=int_value;
        free_node(hfs);
        
    }
    for(Node* nit=temp_node;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_c* c=(template_c*)(nit->value);
        m->delete_cell(m,*c,true);
    }

    free_node(temp_node);temp_node=NULL;
    // for(Node*nit=v1->faces;nit!=NULL;nit=(Node*)(nit->Next))
    for(auto vfit=m->vf_begin(m,*v1);vfit!=m->vf_end(m,*v1);vfit++)
    {
        template_f*f=quote(vfit);
        // template_f*f=(template_f*)(nit->value);
        temp_node=node_overlying(temp_node,f);
        template_v**vs=(template_v**)malloc(sizeof(template_v*)*2);
        vs[0]=f->vertices[0];vs[1]=f->vertices[1];
        f_vs=node_overlying(f_vs,vs);
        //m->delete_cell(m,*c,true);
    }
    for(Node* nit=temp_node;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_f* f=(template_f*)(nit->value);
        m->delete_face(m,*f,true);
    }
    free_node(temp_node);
    for(Node* nit=cell_vs;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_v**vs=(template_v**)(nit->value);
        int *int_len=(int*)(nit->traits);
        my_jiaohuan_vertices_value(vs,v1,v,*int_len);
        my_create_cellfv(m,vs,(*int_len) );
        free(vs);free(int_len);
    }
    for(Node* nit=f_vs;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_v**vs=(template_v**)(nit->value);
        
        my_jiaohuan_vertices_value(vs,v1,v,2);
        if(vs[0]!=vs[1])
        {
            m->create_facev(m,vs,2);
        }
        
        
        free(vs);
    }

    free_node(cell_vs);free_node(f_vs);
    free(cp);
    m->delete_vertex(m,*v1,true);
    
}

static Node* my_inter_get_belong_to_cells(template_v*v,int i)
{

    Node* re=NULL;
    Crossover_Point* cp=(Crossover_Point*)(v->prop);
    if(cp->scp[i].v!=NULL)
    {
        // re=node_copy(cp->scp[i].v->cells);
        for(int j=0;j<cp->scp[i].v->cellsn.size;j++)
        {
            re=node_overlying(re,cp->scp[i].v->cellsn.extra_data[j]);
        }
    }
    else if(cp->scp[i].f!=NULL)
    {
        if(cp->scp[i].f->halffaces[0]->cell!=NULL)
        {
            re=node_overlying(re,cp->scp[i].f->halffaces[0]->cell);
        }
        if(cp->scp[i].f->halffaces[1]->cell!=NULL)
        {
            re=node_overlying(re,cp->scp[i].f->halffaces[1]->cell);
        }
    }
    else if(cp->scp[i].c!=NULL)
    {
        re=node_overlying(re,cp->scp[i].c);
    }
    
    return re;
}
static inline int weak_equal_topology(template_v* v1,template_v*v2)
{
    Node* node1=my_inter_get_belong_to_cells(v1,0);
    Node* node2=my_inter_get_belong_to_cells(v2,0);
    Node* node3=node_intersection(node1,node2);
    free_node(node1);free_node(node2);
    if(node3==NULL){return 0;}
    free_node(node3);
    node1=my_inter_get_belong_to_cells(v1,1);
    node2=my_inter_get_belong_to_cells(v2,1);
    node3=node_intersection(node1,node2);
    free_node(node1);free_node(node2);
    if(node3==NULL){return 0;}
    free_node(node3);
    return 1;
}
// 
static inline int equal_topology(template_v* v1,template_v*v2)
{
    Crossover_Point* cp=(Crossover_Point*)(v1->prop),*cp1=(Crossover_Point*)(v2->prop);

    if(cp->scp[0].f==cp1->scp[0].f&&cp->scp[0].c==cp1->scp[0].c&&cp->scp[0].v==cp1->scp[0].v 
        &&cp->scp[1].f==cp1->scp[1].f&&cp->scp[1].c==cp1->scp[1].c&&cp->scp[1].v==cp1->scp[1].v 
        )
    {
        return 1;
    }

    return 0;
}

static inline int equal_condition_cmp(template_v* v1,template_v*v2,double threshold)
{
    return (equal_topology(v1,v2)&&is_same_point2(v1->point,v2->point,threshold));
}

static inline int weak_equal_condition_cmp(template_v* v1,template_v*v2,double threshold)
{
    // if(v1->faces!=NULL&&v2->faces!=NULL&&v1->faces->value==v2->faces->value)
    if(v1->facesn.size!=0&&v2->facesn.size!=0&&
        v1->facesn.extra_data[0]==v2->facesn.extra_data[0])
    {
        return 0;
    }
    return (weak_equal_topology(v1,v2)&&is_same_point2(v1->point,v2->point,threshold));
}

static inline int weak_equal_condition_cmp1(template_v* v1,template_v*v2,double threshold)
{
    
    return is_same_point2(v1->point,v2->point,threshold);
}
// static inline void equal_condition_handle(template_v* v1,template_v*v2)
// {

// }
//
static inline void my_adjust_connect_two_vertex(Mesh* m,template_v* v1,template_v* v2,
    Mesh2_Crossover_Point* mcp1,Mesh2_Crossover_Point*mcp2)
{
    if(v1==v2){return ;}

    template_v* vs[2]={v1,v2};
    printf("create face:%d %d\n",v1->id,v2->id);
    m->create_facev(m,vs,2);
}
//
static  Node* adjust_edges_to_loop_from_nodes(Node* node,Mesh*m,
    Mesh2_Crossover_Point* mcp1,Mesh2_Crossover_Point*mcp2,double threshold,
    int (*cmp)(template_v* ,template_v* ,double),
    void (*handle)(Mesh*,template_v* ,template_v*,Mesh2_Crossover_Point*,Mesh2_Crossover_Point*))
{
    if(node==NULL)
    {
        return NULL;
    }
    Node* n1=NULL,*n2=NULL;
    Node* nit=(Node*)(node->Next);n1=node;
    template_v* v=(template_v*)(n1->value),*v1=NULL;
    int flag=0;
    printf("v:%d %lf %lf %lf\n",v->id,v->point[0],v->point[1],v->point[2]);
    for(;nit!=NULL;nit=(Node*)(nit->Next))
    {
        v1=(template_v*)(nit->value);
        if(distance_of_two_points(v->point,v1->point,3)<1e-4)
        {
            printf("%d %d :dis:%lf\n ",v1->id,v->id,distance_of_two_points(v->point,v1->point,3) ); 
        }
        //printf("v1:%d %lf %lf %lf\n",v1->id,v1->point[0],v1->point[1],v1->point[2]);
        if(cmp(v,v1,threshold))
        {
            n2=nit;
            flag=1;
            break;
        }
        // if(equal_topology(v,v1))
        // {
            
        //     printf("is equal%d:%lf\n",v1->id,distance_of_two_points(v->point,v1->point,3));
        //     //fabs(p1[0]-p2[0])<=1e-5&&fabs(p1[1]-p2[1])<=1e-5&&fabs(p1[2]-p2[2])<=1e-5
        //     if(!is_same_point2(v->point,v1->point)  )
        //     {
        //         continue;
        //     }
        //     n2=nit;
        //     flag=1;
        //     break;
        // }
    }
    if(n1!=NULL&&n2!=NULL&&flag==1)
    {
        printf("merge two vertices\n");
        handle(m,v,v1,mcp1,mcp2);
        //merge_two_vertices(m,v,v1,mcp1,mcp2);
    //     Node*re=node_remove(node,n1);
    // //printf("node size:%d\n",node_size(re));
    //     re=node_remove(re,n2);
    //     return re;
    }

    // for(nit=(Node*)(node->Next);nit!=NULL;nit=(Node*)(nit->Next))
    // {
    //     v1=(template_v*)(nit->value);
    //     if(distance_of_two_points(v->point,v1->point,3)<1e-4)
    //     {
    //         printf("%d %d :dis:%lf\n ",v1->id,v->id,distance_of_two_points(v->point,v1->point,3) ); 
    //     }
    //     //printf("v1:%d %lf %lf %lf\n",v1->id,v1->point[0],v1->point[1],v1->point[2]);
    //     if(equal_topology(v,v1))
    //     {
            
    //         printf("is equal%d:%lf\n",v1->id,distance_of_two_points(v->point,v1->point,3));
    //         //fabs(p1[0]-p2[0])<=1e-5&&fabs(p1[1]-p2[1])<=1e-5&&fabs(p1[2]-p2[2])<=1e-5
    //         if(!is_same_point2(v->point,v1->point)  )
    //         {
    //             continue;
    //         }
    //         n2=nit;
    //         flag=1;
    //         break;
    //     }
    // }
    
    Node*re=node_remove(node,n1);
    //printf("node size:%d\n",node_size(re));
    re=node_remove(re,n2);


    return re;
}

static int vertex_is_on_the_boundary_of_surfaces(Mesh* m, template_v*v)
{
    Crossover_Point*cp=(Crossover_Point*)(v->prop);
    for(int i=0;i<2;i++)
    {
        if(cp->scp[i].v!=NULL&&m->vertex_is_boundary(m,*(cp->scp[i].v)))
        {                   
            return 1;
        }
        else if(cp->scp[i].f!=NULL&&m->face_is_boundary(m,*(cp->scp[i].f)))
        {
            return 1;
        }
    } 
    return 0;
}





static void my_adjust_connect_vertex2boundary(Mesh* m,Mesh2_Crossover_Point*mcp1,Mesh2_Crossover_Point*mcp2,
    template_v*v,double threshold)
{
    Crossover_Point*cp=(Crossover_Point*)(v->prop);
    Mesh2_Crossover_Point* mcps[2]={mcp1,mcp2};
    for(int i=0;i<2;i++)
    {
        template_f* f=cp->scp[i].f;
        if(f==NULL||!m->face_is_boundary(m,*f))
        {
            continue;
        }
        // if(f==NULL)
        // {
        //     continue;
        // }
        // for(int j=0;j<2;j++)
        // {

            
        // }
        template_c* c=(f->halffaces[0]->cell!=NULL?f->halffaces[0]->cell:f->halffaces[1]->cell);

        Node* node_vs=get_intersections_of_one_cells(c, mcps[i]);
        double dis=threshold;
        template_v*vv=NULL;
        template_v* vs[2]={0};
        for(Node* nit=node_vs;nit!=NULL;nit=(Node*)(nit->Next))
        {
            template_v* v1=(template_v*)(nit->value);
            if(v1==v)
            {
                continue;
            }
            vs[0]=v;vs[1]=v1;
            if(m->get_facev(m,vs,2)!=NULL){continue;}
            double temp_dis=distance_of_two_points(v->point,v1->point,3);
            if(temp_dis<dis)
            {
                vv=v1;dis=temp_dis;
            }

        }

        
        free_node(node_vs);
        if(vv!=NULL)
        {
            vs[0]=v;vs[1]=vv;
            m->create_facev(m,vs,2);
            break;
        }
    }

}
static void my_adjust_attach_vertex2boundary(Mesh* m,Mesh2_Crossover_Point*mcp1,Mesh2_Crossover_Point*mcp2,
    template_v*v,double threshold)
{
    printf("attach v:%d\n",v->id);
    Crossover_Point*cp=(Crossover_Point*)(v->prop);
    Mesh2_Crossover_Point* mcps[2]={mcp1,mcp2};
    for(int i=0;i<2;i++)
    {
        if(cp->scp[i].c!=NULL)
        {
            template_c*c=cp->scp[i].c;
            template_v* v2=NULL;
            for(int j=0;j<c->vertices_size;j++)
            {
                if(is_same_point2(v->point,c->vertices[j]->point,threshold))
                {
                    v2=c->vertices[j];
                    break;
                }

            }
            if(v2!=NULL)
            {
                printf("attach once v:%d v2:%d\n",v->id,v2->id);
                my_erase_value_from_tree(mcps[i]->c2p,c->id,v);
                my_insert_value2tree(mcps[i]->v2p,v2->id,v);
                cp->scp[i].c=NULL;cp->scp[i].v=v2;
                continue;
            }


            template_f* f=NULL;double dis=2*threshold;

            //for(Node* nit=c->halffaces;nit!=NULL;nit=(Node*)(nit->Next))
            for(auto chfit=Mesh_chf_begin(NULL,*c);chfit!=Mesh_chf_end(NULL,*c);chfit++)
            {
            
                template_hf*hf=quote(chfit);
                template_f*f1=(template_f*)(hf->face);
            
                double temp_dis=distance_of_from_line_segment2point(f1->vertices[0]->point,
                    f1->vertices[1]->point,v->point);
                //printf("vvvvv id:%d f:%d dis:%lf",v->id,f1->id,temp_dis);
                if(temp_dis<dis)
                {
                    dis=temp_dis;f=f1;
                }
            
            }
            if(f!=NULL)
            {
                printf("attach once v:%d\n",v->id);
                my_erase_value_from_tree(mcps[i]->c2p,c->id,v);
                my_insert_value2tree(mcps[i]->f2p,f->id,v);
                cp->scp[i].c=NULL;cp->scp[i].f=f;
            }
            continue;
        }
        else if(cp->scp[i].f!=NULL)
        {
            template_f* f=cp->scp[i].f;
            template_v* v2=NULL;
            for(int j=0;j<2;j++)
            {
                if(is_same_point2(v->point,f->vertices[j]->point,threshold))
                {
                    v2=f->vertices[j];
                    break;
                }
            }
            if(v2!=NULL)
            {
                //printf("attach once v:%d v2:%d\n",v->id,v2->id);
                my_erase_value_from_tree(mcps[i]->f2p,f->id,v);
                my_insert_value2tree(mcps[i]->v2p,v2->id,v);
                cp->scp[i].f=NULL;cp->scp[i].v=v2;
                continue;
            }
        }
       
        //
        //my_insert_value2tree
    }

}


//检测并调整拓扑
//合并了拓扑强相等并距离足够近的点
//尝试创建face，连接两个弱拓扑相等点（距离最够近，落在相同cell上）
//
static Node* my_adjust_get_moduan_vertices(Mesh* m)
{
    Node* node1=NULL;
    for(auto it=m->v_begin(m);it!=m->v_end(m);it++)
    {
        // int size=node_size(quote(it)->faces);
        int size=quote(it)->facesn.size;
        if(size ==1||size==0||size%2==1)
        {
            node1=node_overlying(node1,quote(it));
        }
    }
    return node1;   
}

void adjust_mesh_topology_of_cintersecting_curve(Mesh* m,Mesh2_Crossover_Point*mcp1,Mesh2_Crossover_Point*mcp2)
{
    //这种情况也允许存在，理论上不需要调整，需要调整的是剖分算法
   
    Node* node1=my_adjust_get_moduan_vertices(m);
    printf("ajust mesh topology\n");

  
    for(Node* nit=node1;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_v* v=(template_v*)(nit->value);
       
        my_adjust_attach_vertex2boundary(m,mcp1,mcp2,
            v,2e-6);
    }

    printf("node1 size:%d\n",node_size(node1));
    free_node(node1);
    
    node1=my_adjust_get_moduan_vertices(m);
    for(Node* nit=node1;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_v* v=(template_v*)(nit->value);
        printf("my:%d %lf %lf %lf\n",v->id,v->point[0],v->point[1],v->point[2]);
        my_adjust_connect_vertex2boundary(m,mcp1,mcp2,
            v,2e-5);

    }
    printf("node1 size:%d\n",node_size(node1));
    
    free_node(node1);


    node1=my_adjust_get_moduan_vertices(m);
    while(node1!=NULL)
    {
        printf("ajust once %d \n",node_size(node1));

        node1 = adjust_edges_to_loop_from_nodes(node1,m,mcp1,mcp2,1e-5,
            equal_condition_cmp,merge_two_vertices);
    }
    printf("***************************\n");
    node1=my_adjust_get_moduan_vertices(m);
    while(node1!=NULL)
    {
        printf("ajust once %d \n",node_size(node1));

        node1 = adjust_edges_to_loop_from_nodes(node1,m,mcp1,mcp2,2e-5,
            weak_equal_condition_cmp,my_adjust_connect_two_vertex);
    }
    node1=my_adjust_get_moduan_vertices(m);
    while(node1!=NULL)
    {
        printf("ajust once %d \n",node_size(node1));

        node1 = adjust_edges_to_loop_from_nodes(node1,m,mcp1,mcp2,5e-5,
            weak_equal_condition_cmp1,my_adjust_connect_two_vertex);
    }
    // template_v* v1=m->get_vertexp(m,12999);
    // template_v* v2=m->get_vertexp(m,12998);
    // if(weak_equal_condition_cmp(v1,v2,1e-4))
    // {
    //     printf("v1 %d v2 %d is weak equal \n ",v1->id,v2->id);
    // }
    
    // 
    
    // 删除这样的faces，它的两段落在l落在同一点上
    //
}